package com.gylang.im.core.util;

import com.gylang.im.core.enums.ResultEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Base64Utils;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * rsa秘钥工具
 *
 * @author gylang,
 */
@Slf4j
public class RsaUtils {


    private static final int DEFAULT_KEY_SIZE = 2048;

    /**
     * 根据密文 生成ras公钥私钥 并写入文件
     *
     * @param publicKeyFileName  公钥文件名
     * @param privateKeyFileName 私钥文件名
     * @param secret             生成秘钥的密文
     * @throws
     */
    public static void generateKey(String publicKeyFileName, String privateKeyFileName, String secret, int keySize) throws Exception {

        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        SecureRandom secureRandom = new SecureRandom(secret.getBytes());
        keyPairGenerator.initialize(Math.max(keySize, DEFAULT_KEY_SIZE), secureRandom);
        KeyPair keyPair = keyPairGenerator.genKeyPair();
        // 获取公钥并写出
        byte[] publicKeyBites = keyPair.getPublic().getEncoded();
        publicKeyBites = Base64.getEncoder().encode(publicKeyBites);
        writeFile(publicKeyFileName, publicKeyBites);
        //获取私钥并写出
        byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
        privateKeyBytes = Base64.getEncoder().encode(privateKeyBytes);
        writeFile(privateKeyFileName, privateKeyBytes);
    }

    private static byte[] readFile(String fileName) throws Exception {
        return Files.readAllBytes(new File(fileName).toPath());
    }

    private static void writeFile(String destPath, byte[] content) throws IOException {

        File dest = new File(destPath);
        if (!dest.exists()) {
            dest.createNewFile();
        }
        FileOutputStream fos = new FileOutputStream(dest);
        fos.write(content);
        fos.close();

    }

    /**
     * 获取私钥
     *
     * @param bytes 私钥字节形式
     * @return 获取私钥
     */
    private static PrivateKey getPrivateKey(byte[] bytes) throws NoSuchAlgorithmException, InvalidKeySpecException {
        bytes = Base64.getDecoder().decode(bytes);
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes);
        KeyFactory factory = KeyFactory.getInstance("RSA");
        return factory.generatePrivate(spec);
    }

    public static PrivateKey getPrivateKey(String flieName) throws Exception {
        byte[] bytes = readFile(flieName);
        return getPrivateKey(bytes);
    }


    /**
     * 获取公钥
     *
     * @param bytes 公钥字节信息
     * @return 获取公钥
     */
    private static PublicKey getPublicKey(byte[] bytes) throws NoSuchAlgorithmException, InvalidKeySpecException {
        bytes = Base64.getDecoder().decode(bytes);
        X509EncodedKeySpec spec = new X509EncodedKeySpec(bytes);
        KeyFactory factory = KeyFactory.getInstance("RSA");
        return factory.generatePublic(spec);
    }

    public static PublicKey getPublicKey(String flieName) throws Exception {
        byte[] bytes = readFile(flieName);
        return getPublicKey(bytes);
    }

    public static String encrypt(Key key, String content) {


        try {
            //初始化密码器
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, key);
            System.out.println(content.getBytes(StandardCharsets.UTF_8).length);
            //加密
            byte[] encryptByte = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));

            return Base64Utils.encodeToString(encryptByte);

        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
            e.printStackTrace();
        }
        return null;
    }


    public static String decrypt(Key key, String content) {


        try {
            //生成公钥对象

            //初始化密码器
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, key);

            //解密
            byte[] encryptByte = cipher.doFinal(Base64Utils.decodeFromString(content));

            return new String(encryptByte, StandardCharsets.UTF_8);

        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException | IllegalArgumentException e) {
            log.info("RsaUtils - decrypt 解密失败 ==  {}", e.getMessage());
            ResultEnum.PARAMS_ERROR.bizException();
        }
        return null;
    }
}
